<template>
  <el-dialog :title="$t('product.createQrcode')" :visible.sync="visible" top="50px" width="650px">
    <div class="dialog-container">
      <div class="content">
        <div class="generate-type-tabs mar-b-16 flex-x jus-center" v-if="allowQrCodeImport">
          <el-radio-group v-model="generateType" @change="generateTypeChange">
            <el-radio-button label="automatically">{{ $t('product.component.qrcodeDialog.automatically') }}</el-radio-button>
            <el-radio-button label="manualImport">{{ $t('product.component.qrcodeDialog.manualImport') }}</el-radio-button>
          </el-radio-group>
        </div>
        <div class="automatically-wrapper" v-if="generateType == 'automatically'">
          <div class="input-tip mar-b-12">{{ $t('product.component.qrcodeDialog.tip4') }}</div>
          <el-input class="mar-b-12" v-model="createNum" :max="margin" min="0" type="number"></el-input>
          <div class="qrcode-margin-tip">
            <i18n path="product.component.qrcodeDialog.text6">
              <span place="num" class="qrcode-margin-num mar-l-5 mar-r-5">{{ margin }}</span>
            </i18n>
          </div>
        </div>
        <div class="manual-import-wrapper" v-if="generateType == 'manualImport'">
          <div class="label1">{{ $t('product.component.qrcodeDialog.text7') }}</div>
          <div class="label2 mar-b-12">{{ $t('product.component.qrcodeDialog.text8', {max: optionMax}) }}</div>
          <div class="batch-input-wrap mar-b-8">
            <textarea :value="optionText" @input="updateOptionText" @blur="validateIsExist" :placeholder="$t('product.component.qrcodeDialog.text9', {max: optionMax})"></textarea>
            <div v-if="errMessage" class="err-msg mar-t-5">{{ errMessage }}</div>
          </div>
          <div class="label3">
            <i18n path="product.component.qrcodeDialog.text10">
              <span place="num1" class="batch-input-num mar-l-5 mar-r-5">{{ optionNum }}</span>
              <span place="num2" class="qrcode-margin-num mar-l-5 mar-r-5">{{ margin }}</span>
            </i18n>
          </div>
        </div>
      </div>
    </div>

    <span slot="footer" class="dialog-footer flex-x jus-bet">
      <div class="dialog-footer-left">
        <el-button type="text" @click="openStyleDialog()">{{ $t('product.component.qrcodeDialog.title3') }}</el-button>
      </div>
      <div class="dialog-footer-right">
        <el-button @click="createCode()" :disabled="pending" v-track="$track.formatParams('QRCODE_ONLY_CREATE', null, 'CREATE_QRCODE_BTN')">{{$t("product.component.qrcodeDialog.btn3")}}</el-button>
        <el-button @click="createCode(downloadCode)" :disabled="pending" v-if="canProductCodeDownload" v-track="$track.formatParams('QRCODE_CREATE_AND_DOWNLOAD_URL', null, 'CREATE_QRCODE_BTN')">{{$t('product.component.qrcodeDialog.btn4')}}</el-button>
        <el-button type="primary" :disabled="pending" @click="createCode(downloadImg)" v-if="canProductCodeDownload" v-track="$track.formatParams('QRCODE_CREATE_AND_DOWNLOAD_IMG', null, 'CREATE_QRCODE_BTN')">{{$t('product.component.qrcodeDialog.btn5')}}</el-button>
      </div>
    </span>

    <qrcode-style-dialog ref="qrcodeStyleDialog" :init-data="initData" @checkList="changeCheckList"></qrcode-style-dialog>
  </el-dialog>
</template>

<script>
import * as productQrcode from '@src/api/productQrcode';
import { SELECT_OPTION_LENGTH_MAX } from '@src/component/form/config'
import { getRootWindow } from '@src/util/dom';
import VersionMixin from '@src/mixins/versionMixin/index.ts';
import QrcodeStyleDialog from './QrcodeStyleDialog.vue';
import { t } from '@src/locales';

export default {
  name: 'new-qrcode-dialog',
  mixins: [VersionMixin],
  data() {
    return {
      visible: false,
      generateType: 'automatically',
      optionText: '',
      optionMax: 1000,
      errMessage: '',
      checkList: [],
      fieldList: [
        { displayName: t('product.component.qrcodeDialog.companyLogo'), fieldName: 'companyLogo' },
        { displayName: t('product.component.qrcodeDialog.companyName'), fieldName: 'companyName' },
      ],
      createNum: '',
      margin: 0,
      pending: false,
    };
  },
  computed: {
    auths() {
      return this.initData?.auths;
    },
    qrcodeEnabled() {
      return this.initData?.qrcodeEnabled;
    },
    canProductCodeDownload() {
      return this.auths?.PRODUCT_CODE_DOWNLOAD;
    },
    allowQrCodeImport() {
      return this.qrCodeImportAndAutoRelationGray && this.qrcodeEnabled && this.initData?.allowQrCodeImport == 'true';
    },
    // 允许二维码导入和关联产品灰度
    qrCodeImportAndAutoRelationGray() {
      const RootWindow = getRootWindow(window)
      return RootWindow.grayAuth?.qrCodeImportAndAutoRelation || false;
    },
    optionNum() {
      if (!this.optionText) return 0;
      return this.optionText.split('\n').filter(Boolean).length;
    },
  },
  props: {
    initData: {
      type: Object,
      default: () => {},
    },
  },
  watch: {
    createNum(val) {
      if (val.indexOf('.') > -1) {
        this.createNum = val.slice(0, -1);
        return;
      }
      if (val < 0) {
        this.createNum = '0';
      } else if (val > this.margin) {
        this.createNum = String(this.margin);
      }
    },
  },
  mounted() {
    this.getProductFields();
  },
  methods: {
    generateTypeChange() {
      this.getMargin();
    },
    // 仅生成
    async createCode(callback) {
      try {
        if (this.generateType == 'automatically') {
          if (!this.createNum || this.createNum == 0) return this.$message.warning(t('product.component.qrcodeDialog.tip2'));
        } else {
          if (!this.optionText) return this.$message.warning(t('product.component.qrcodeDialog.tip10'));
          if (this.errMessage) return;
        }
        this.pending = true;
        const fn = this.generateType == 'automatically' ? productQrcode.createQrCode : productQrcode.batchInputQrCode;
        let params = {
          createNum: this.createNum
        }
        if (this.generateType == 'manualImport') {
          params = {
            qrCodeList: this.optionText.split('\n')
          }
        }
        let { status, message, data } = await this.checkNumExceedLimitAfterHandler(fn(params));
        this.pending = false;
        if (status === 0) {
          this.optionText = '';
          if (callback) return callback(data);
          this.visible = false;
          this.$emit('createCode');
        } else {
          this.$message.error(message);
        }
      } catch (err) {
        this.pending = false;
        console.error(err);
      }
    },
    // 下载二维码编号
    async downloadCode(ids) {
      this.pending = true;
      try {
        let { status, message } = await productQrcode.exportExcel({ ids: ids.join(',') });
        this.pending = false;
        this.$platform.alert(message);
        if (status === 0) {
          this.optionText = '';
          this.visible = false;
          this.$emit('createCode');
          window.parent.showExportList();
          window.parent.exportPopoverToggle(true);
        }
      } catch (err) {
        this.pending = false;
        console.error(err);
      }
    },
    // 下载二维码图片
    async downloadImg(data) {
      this.pending = true;
      try {
        let productExport = `${this.checkList.join(',')},qrcodeId`;
        const params = {
          productExport,
          ids: data.join(','),
        };
        let { status, message } = await productQrcode.exportImg(params);
        this.pending = false;
        this.$platform.alert(message);
        if (status === 0) {
          this.optionText = '';
          this.visible = false;
          this.$emit('createCode');
          window.parent.showExportList();
          window.parent.exportPopoverToggle(true);
        }
      } catch (err) {
        this.pending = false;
        console.error(err);
      }
    },
    // 获取余量
    async getMargin() {
      try {
        let { data, status, message } = await productQrcode.getMargin();
        if (status === 0) {
          this.margin = data;
        } else {
          this.$message.error(message);
        }
      } catch (err) {
        console.error(err);
      }
    },
    updateOptionText(event) {
      this.optionText = event.target.value;
      let newOption = this.optionText.split('\n');
      this.errMessage = this.validateOptions(newOption);
    },
    validateOptions(opts){
      let options = opts[opts.length - 1] == null ? opts.slice(0, -1) : opts;
      let message = [];
    
      // 验证数量
      if(options.length > this.optionMax){
        message.push(t('product.component.qrcodeDialog.tip5', {max: this.optionMax}));
      }

      // 验证数量是否超过余量
      if (options.length > this.margin) {
        message.push(t('product.component.qrcodeDialog.tip9', {num1: options.length, num2: this.margin}));
      }
    
      // 是否有空白项
      if(options.some(item => !item)){
        message.push(this.t('common.base.tip.cantHaveNullOption'));
      }
    
      // 验证每一项长度
      let errIndex = options.map((item, index) => item.length > SELECT_OPTION_LENGTH_MAX ? index + 1 : -1).filter(item => item != -1);
      if(errIndex.length > 0){
        message.push(this.t('common.form.preview.relatedCatalog.des5', {data1: errIndex.join('，'), data2: SELECT_OPTION_LENGTH_MAX}));
      }

      // 验证只能输入英文和数字
      const regex = /^[a-zA-Z0-9]+$/;  
      let errIndex2 = options.map((item, index) => !regex.test(item) ? index + 1 : -1).filter(item => item != -1);
      if(errIndex2.length > 0){
        message.push(t('product.component.qrcodeDialog.tip7', {data: errIndex2.join('，')}));
      }

      // 验证重复项
      let repeatMessage = this.checkDuplicates(options);
      message = message.concat(repeatMessage);
    
      return message.length > 0 ? message.join(',') : null;
    },
    // 验证重复项
    checkDuplicates(arr) {  
      let message = [];
      const seen = {}; // 用于跟踪已经遇到的元素  
      const duplicates = []; // 用于存储重复元素的索引  
      
      for (let i = 0; i < arr.length; i++) {  
        const value = arr[i];  
        if (seen[value]) {  
          // 如果已经存在，说明是重复项  
          duplicates.push(i); // 将当前索引添加到重复项数组中  
          seen[value].push(i); // 将当前索引添加到已存在值的索引数组中  
        } else {  
          seen[value] = [i]; // 否则，初始化索引数组并添加当前索引  
        }  
      }  
      
      if (duplicates.length > 0) {  
        // 如果有重复项，构建并输出提示信息  
        for (let j = 0; j < duplicates.length; j++) {  
          const firstIndex = seen[arr[duplicates[j]]][0]; // 获取第一个重复项的索引  
          message.push(t('product.component.qrcodeDialog.tip6', {num1: firstIndex + 1, num2: duplicates[j] + 1}));
          break;
        }  
      }
      return message;
    },
    validateIsExist() {
      if (!this.optionText) return
      productQrcode.inputQrCodeCheckExist({
        qrCodeList: this.optionText.split('\n')
      }).then(res => {
        if (res?.result?.length) {
          this.errMessage = t('product.component.qrcodeDialog.tip8', {data: res.result.join(',')})
        }
      })
    },
    open() {
      this.getMargin();
      this.visible = true;
    },
    openStyleDialog() {
      this.$refs.qrcodeStyleDialog.open()
    },
    changeCheckList(value) {
      this.checkList = value || [];
    },
    // 获取产品自定义字段
    async getProductFields() {
      try {
        let { status, data, message } = await productQrcode.getProductFields({ isFromSetting: false });
        if (status === 0) {
          const filterType = ['autograph', 'select', 'attachment', 'separator', 'info'];
          // 获取到被过滤的字段名称map
          const filterFieldsNameMap = data
            .map(f => {
              return filterType.includes(f.formType) || f.setting?.isSubForm ? f.fieldName : '';
            })
            .filter(f => f && f.trim());

          data = data.filter(item => !filterFieldsNameMap.includes(item.fieldName));
          this.fieldList = this.fieldList.concat(data);
          const allFieldsNameMap = this.fieldList.map(f => f.fieldName);

          if (!this.hasCompanyLogo) {
            this.fieldList[0].disabled = true;
          }
          const checkFields = localStorage.getItem(`qrcode_check_items_${this.initData.domain}`);
          if (checkFields) {
            // 兼容，历史选中的不能展示的类型需要被清除选中
            this.checkList = checkFields.split(',').filter(f => !filterFieldsNameMap.includes(f) && allFieldsNameMap.includes(f));
            const logoIndex = this.checkList.findIndex(item => item === 'companyLogo');
            if (logoIndex > -1 && !this.hasCompanyLogo) {
              this.checkList.splice(logoIndex, 1);
            }
          }
        } else {
          this.$message.error(message);
        }
      } catch (err) {
        console.error(err);
      }
    },
  },
  components:{
    [QrcodeStyleDialog.name]: QrcodeStyleDialog,
  }
};
</script>

<style lang="scss" scoped>
.dialog-container {
  .content {
    padding: 24px;
  }
  .generate-type-tabs {
    ::v-deep .el-radio-button__inner {
      width: 150px;
    }
  }
  .automatically-wrapper {
    height: 306px;
    padding: 12px;
    background: #f7f8f8;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    .input-tip, .qrcode-margin-tip {
      font-size: 16px;
      font-weight: 400;
      line-height: 24px;
      color: #595959;
    }
    ::v-deep .el-input {
      width: 166px;
      height: 40px;
      border-radius: 4px;
    }
    ::v-deep .el-input__inner {
      height: 40px;
      line-height: 40px;
      font-size: 16px;
    }
    .qrcode-margin-num {
      font-weight: 700;
      font-size: 20px;
      color: #E6A23C;
    }
  }
  .manual-import-wrapper {
    padding: 12px;
    background: #F7F8F8;
    .label1 {
      font-weight: 500;
      line-height: 22px;
      margin-bottom: 4px;
      color: #595959;
    }
    .label2 {
      font-size: 12px;
      line-height: 20px;
      color: #595959;
    }
    .batch-input-wrap {
      textarea {
        width: 100%;
        height: 194px;
        padding: 8px 2px 2px 12px;
        background: #FFFFFF;
        border-radius: 2px;
      }
      .err-msg {
        font-size: 12px;
        line-height: 20px;
        color: #f56c6c;
      }
    }
    .batch-input-num {
      font-size: 18px;
      font-weight: 700;
    }
    .qrcode-margin-num {
      font-size: 18px;
      font-weight: 700;
      color: #E6A23C;
    }
  }
}
</style>